import time
import wiringpi as gpio
import json
import os
from PyQt4 import QtCore 
from Motor import Motor, MotorError

class MechanicalSystem(QtCore.QThread):

    ErrorSignal = QtCore.pyqtSignal(str)
    FinshSignal = QtCore.pyqtSignal(bool,int)

    def __init__(self,init_Position = 0,parent = None):
        super(MechanicalSystem,self).__init__(parent)

        """
            plus_port = 13
            dir_port = 6
            stop_port = 19
        """
        self.motor_port = [13,6,19]
        # Creat a motor instance
        self.motor = Motor(self.motor_port)
        self.motor_start()
        # Set your inital position and save it in current_position.json
        self.current_position = init_Position
        
        self.motor.set_position(init_Position)

    def set_dir_distance_info(self,direction,distance):
        self.__direction = direction
        self.__distance = distance
        

    def get_current_position(self):
        self.current_position = self.motor.get_position()
        return self.current_position
    
    def motor_move_mm(self,dir_commd,distance):
        """
            This function can drive slider to move forward or back with your direction commd
            If you use a wrong dir_commd,this function can throw a exception (MotorError) o upper
            
            Return: the status of your motor moving,'True' means motor has move the rignt position
            and 'Flase' means that some errors occured when the slider move,which could be oversteps' errors
            or usingError. In other words,the exception also can be returned
        """
        distance = float(distance)
        status = False
        self.motorError = None
        if dir_commd == '+':
            try:
                status = self.motor.move_forward(distance)
            except MotorError as e:
                self.motorError = e
        elif dir_commd == '-':
            try:
                status = self.motor.move_back(distance)
            except MotorError as e:
                self.motorError = e
        else:
            status = False
            raise MotorError('usingError')

        return status,self.motorError

    def run(self):
        """
            This function can be run by upper,and throw some signals about status and errors information
            Attention:
                If your dir_commd is wrong,it can throw a 'usingError' exception;
                If your distance is over __length_MAX or __length_MIN, it will throw a "OverHigh or OverLow" exception
                If your distence is in [__length_MAX,__length_MIN],it will throw a signal with 'True'
                and position.
        """
        status = False
        try:
            status,Motor_Error = self.motor_move_mm(self.__direction,self.__distance)
            if status == False:
                self.ErrorSignal.emit(Motor_Error.errorinfo)
            else:
                self.FinshSignal.emit(status,self.get_current_position())
        except MotorError as e:
            self.motorError = e
            self.ErrorSignal.emit(self.motorError.errorinfo)

        self.motorError = None
        # set these attribute as initial seeting
        self.set_dir_distance_info(self.__direction,0)

    def motor_start(self):
        """
            This function is supposed to be run when you realize your motor instance.
        """
        self.motor.stop_start(False)

    def motor_stop(self):
        """
            This function can make motor stop and the slider move to original position.
        """
        try:
            self.motor.move_2_original()
        except MotorError:
            a = 1
        finally:
            self.motor.stop_start(True)

if __name__ == "__main__":
    
    MS = MechanicalSystem(100)

    MS.set_dir_distance_info('+', 50)
    MS.run()
    print MS.get_current_position()
    MS.motor_stop()
    print MS.get_current_position()
